import { Router } from '../router'
import { cond, BadRequestError, UnauthorizedError } from '../error'
import conf from '../config'
import * as GitHub from 'github-api'
import * as https from 'https'
import * as fs from 'fs'
import * as path from 'path'

var router = new Router()
export default router

const PAGE_INDEX = fs.readFileSync(path.join(__dirname, '../components/index.html'), 'utf8')

router.get('/', async (req, res) => {
  if (req.cookies.accessToken) {
    res.writeHead(200, {
      'Content-Type': 'text/html'
    })
    res.end(PAGE_INDEX)
  } else {
    res.writeHead(302, {
      'Location': `https://github.com/login/oauth/authorize?client_id=${conf.oauth.id}`
    })
    res.end()
  }
})

router.get('/github/profile', async (req, res) => {
  cond(req.cookies.accessToken, BadRequestError)
  var profile = await new Promise((complete, fail) => {
    var gh = new GitHub({
      token: req.cookies.accessToken
    })
    gh.getUser().getProfile(function (err: Error, result: any) {
      if (err) {
        fail(err)
      } else {
        complete(result)
      }
    })
  })
  res.writeHead(200, {'Content-Type': 'text/html'})
  res.end(JSON.stringify(profile))
})

router.get('/auth/github', async (req, res) => {
  function getAccessToken(id: string, secret: string, code: string): Promise<string> {
    return new Promise<string>((complete, fail) => {
      var req: any = https.request({
        hostname: 'github.com',
        method: 'POST',
        path: '/login/oauth/access_token' + 
              `?client_id=${id}` +
              `&client_secret=${secret}` + 
              `&code=${code}`
      }, function (res) {
        res.setEncoding('utf8')
        var body = ''
        res.on('data', (d) => body += d)
        res.on('end', () => {
          try {
            var token = require('querystring').parse(body).access_token
            cond(token, UnauthorizedError)
            complete(token)
          } catch (e) {
            fail(e)
          }
        })
      })
      req.on('error', (err: Error) => {
        req.abort()
        fail(err)
      })
      req.end()
    })
  }
  cond(req.uri.query.code, BadRequestError, 'invalid code')
  var accessToken = await getAccessToken(conf.oauth.id, 
                                         conf.oauth.secret, 
                                         req.uri.query.code)
  res.writeHead(302, {
    'Location': '/',
    'Set-Cookie': `accessToken=${accessToken}; max-age=${conf.oauth.expireTime}; path=\/; HttpOnly` // TODO: secure;  
  });
  res.end(accessToken)
})